﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using UCS.XNA.CombatBiplanes.Synchronization;
using UCS.XNA.Utils;

namespace UCS.XNA.CombatBiplanes
{
    public class Rocket : IActionExecutor
    {
        #region Private Members

        private Texture2D _texture;
        private Texture2D _explosionTexture;
        private Vector2 _origin;
        private Vector2 _speed;
        private SpriteBatch _spriteBatch;
        private float _speedFactor = 10;
        private float _scale = 0.7f;
        private AnimatedSprite _explosion;

        #endregion

        #region Attributes and Properties

        private Vector2 _position;
        public Vector2 Position
        {
            get { return this._position; }
        }

        private Rectangle _bounds;
        public Rectangle Bounds
        {
            get { return _bounds; }
        }

        private float _angle;
        public float Angle
        {
            get { return this._angle; }
            set
            {
                this._angle = value;

                this.InitializeSpeed();
            }
        }

        private Color[,] _colorData;
        public Color[,] ColorData
        {
            get { return _colorData; }
        }

        private Airplane _source;
        public Airplane Source
        {
            get { return this._source; }
            set { this._source = value; }
        }

        private int _id;
        public int ID
        {
            get { return this. _id; }
            set { this._id = value; }
        }

        public bool IsExploding
        {
            get { return this._explosion != null; }
        }

        #endregion

        #region Events

        public event EventHandler<RocketEventArgs> Exploded;

        #endregion

        #region Constructors

        public Rocket(Texture2D texture, Texture2D explosionTexture, Vector2 position, Airplane source, SpriteBatch spriteBatch)
        {
            this._texture = texture;
            this._explosionTexture = explosionTexture;
            this._position = position;
            this._source = source;
            this._spriteBatch = spriteBatch;

            this.InitializeBounds();
            this.InitializeOrigin();
            this.InitializeSpeed();
            this.InitializeColorData();
        }

        #endregion

        #region Private Methods

        private void InitializeBounds()
        {
            this._bounds = new Rectangle((int)this._position.X, (int)this._position.Y, this._texture.Width, this._texture.Height);
        }

        private void InitializeOrigin()
        {
            this._origin = new Vector2(this._texture.Width / 2, this._texture.Height / 2); 
        }

        private void InitializeSpeed()
        {
            this._speed = new Vector2((float)Math.Cos(this._angle / (180 / Math.PI)), (float)Math.Sin(this._angle / (180 / Math.PI))) * this._speedFactor;
        }

        private void InitializeExplosion()
        {
            this._explosion = new AnimatedSprite(this._explosionTexture, new Rectangle(0, 0, 64, 64), 25, 64, 64, this._spriteBatch);
            Rectangle rect = new Rectangle();
            rect.X = Convert.ToInt32(this._position.X + this._bounds.Width / 2 - this._explosion.Bounds.Width / 2);
            rect.Y = Convert.ToInt32(this._position.Y + this._bounds.Height / 2 - this._explosion.Bounds.Height / 2);
            rect.Width = this._explosion.Bounds.Width;
            rect.Height = this._explosion.Bounds.Height;
            this._explosion.Bounds = rect;
            this._explosion.AnimationFinished += (sender, e) =>
            {
                if (this.Exploded != null)
                    this.Exploded(this, new RocketEventArgs(this));

                this._explosion = null;
            };
        }

        private void InitializeColorData()
        {
            Color[] colors1D = new Color[this._texture.Width * this._texture.Height];
            this._texture.GetData(colors1D);

            this._colorData = new Color[this._texture.Width, this._texture.Height];
            for (int x = 0; x < this._texture.Width; x++)
                for (int y = 0; y < this._texture.Height; y++)
                    this._colorData[x, y] = colors1D[x + y * this._texture.Width];
        }

        #endregion

        #region Public Methods

        public void Update(GameTime gameTime)
        {
            if (this._explosion == null)
            {
                this._position += this._speed;
                this.InitializeBounds();
            }
            else
                this._explosion.Update(gameTime);
        }

        public void Draw(GameTime gameTime)
        {
            if (this._explosion == null)
            {
                this._spriteBatch.Begin();
                this._spriteBatch.Draw(this._texture, this._position, null, Color.White, (float)(this._angle / (180 / Math.PI)), this._origin, this._scale, SpriteEffects.None, 0);
                this._spriteBatch.End();
            }
            else
                this._explosion.Draw(gameTime);
        }

        public Matrix GetMatrix()
        {
            Matrix matrix = Matrix.CreateTranslation(-this._origin.X, -this._origin.Y, 0);
            matrix *= Matrix.CreateRotationZ((float)(this._angle / (180 / Math.PI)));
            matrix *= Matrix.CreateScale(this._scale);
            matrix *= Matrix.CreateTranslation(this._position.X, this._position.Y, 0);

            return matrix;
        }

        public void Explode()
        {
            this.InitializeExplosion();

            this._explosion.Start();
        }

        public void Execute(ActionType actionType, int[] parameters)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
